/****************************************************************
 * Programa que extrai da entrada para efetuar o filtro da Base	*
 * de Dados														*
 * 																*
 * Autora: Cristina Teixeira de Oliveira						*
 * e-mail: cto@icmc.usp.br										*
 * *************************************************************/
 
/****************************************************************
 * Ao chamar a função, devem ser passados um arquivo de entrada *
 * Ex.: extraiEntrada arquivo1 									*
 * Onde, arquivo1 irá conter o RNAnc a ser procurado na base.	*
 * **************************************************************/ 
 
#include <stdio.h> 
#include <math.h>
#include <string.h>
#include <stdlib.h>


//#include <exception>

#define TAM_MAX_SEQ 1000 
#define _GNU_SOURCE
#define MAX_SUBCADEIAS 1000

int inicializaVetorSubcadeia(int *filtroSubcadeia){
	int i;
	
	for (i=0; i<MAX_SUBCADEIAS; i++){
		filtroSubcadeia[i]=0;
	}
	
	return 1;
}

unsigned long int calculaFiltroSubcadeia(int *filtroSubcadeia){
	int i;
	unsigned long int total = 0;
	
	for (i=0; i<MAX_SUBCADEIAS; i++){
		// Usando o	total = calculaFiltroSubcadeia(filtroSubcadeia); cálculo polinomial: x + y2 + z3 +...		
		//total = (pow(filtroSubcadeia[i],(i+1))+total);
		// Usando o cálculo linear: x + 2y + 3z + ...
		total = (unsigned long int)(filtroSubcadeia[i]*(i+1)+total);
		/*if (filtroSubcadeia[i] != 0){
			printf("\tIndice: %d Total: %d", i, filtroSubcadeia[i] );		 
		}*/
	}
	return total;
}

/****************************************************************
 * A funcao extraiSubCadeias(char *estrutura, file *arquivo)	*
 * grava em arquivo os talos/subcadeias encontradas em			*
 * estrutura.													*
 * 																*
 * As subcadeias extraidas nesta função são cadeias 			*
 * independentes, começando e finalizando com um pereamento.	*	
 * *************************************************************/
char *extraiSubCadeias(char *estrutura, int *contSubCadeias){
	int tamSeq = strlen(estrutura);
	char talo[tamSeq];
	char *subcadeias = malloc(strlen(estrutura)*3);	
	int cont, inicio, tamSubCadeias, i, j;
	int contPareado, contNaoPar;
	unsigned long int total;
	int filtroSubcadeia[MAX_SUBCADEIAS];
	int tamFiltroSubcadeia;	
	
	cont = 0;
	contPareado = 0;
	contNaoPar = 0;
	*contSubCadeias = 0;
	tamSubCadeias = 0;
	tamFiltroSubcadeia = 0;
	
	int tamMaxSeq = strlen(estrutura);tamFiltroSubcadeia = 0;
	
	if (inicializaVetorSubcadeia(filtroSubcadeia) != 1) printf("\nErro na inicialização do vetor!\n");	
	
	for (i=0; i<tamSeq; i++){

		// Extrai os Intervalos entre as subsequencias
		if ((cont==0)&&(estrutura[i]=='.')){ //-> contabilizar apenas fora da subcadeia
		//if (estrutura[i]=='.'){
			contNaoPar++;
		}		
		else if (estrutura[i]=='(') { 
			// Se o contador estava zerado deve-se guardar início da posição da subsequencia
			if (cont==0) inicio=i;  
			// Armazena o numero de pareamentos em nivel
			filtroSubcadeia[cont]++;
			if ((cont+1)>tamFiltroSubcadeia) tamFiltroSubcadeia = cont +1;  
			cont++;
			contPareado++;			
		}
		else if (estrutura[i]==')') {
			cont-- ; 
			if (cont==0){
				(*contSubCadeias)++;
				// Guardar subcadeia encontrada
				// Da posicao "inicial" ate "i"
				// concatenar subsequencia com o intervalo encontrado 
				
				//Separando subcadeias
				//Decidir qual vai ser o separador
				
				if (tamSubCadeias > 0) {
					subcadeias[tamSubCadeias] = '\t';
					tamSubCadeias++;
				}	
				
				// Copiando subcadeia
				for(j=inicio; j<=i; j++){								
    				subcadeias[tamSubCadeias] =  estrutura[j];
    				tamSubCadeias++;
  				}
			}			
		}						
	}			
	subcadeias[tamSubCadeias] =  '\0';
	total = calculaFiltroSubcadeia(filtroSubcadeia);	
	sprintf( subcadeias, "%s\t%d", subcadeias, contPareado);	
	sprintf( subcadeias, "%s\t%d\t%lu", subcadeias, contNaoPar, total);
	
	sprintf( subcadeias, "%s\t%d", subcadeias, tamFiltroSubcadeia);
	
	for (j=0; j<tamFiltroSubcadeia; j++){
		//printf("\n Filtro[%d]: %d", j, filtroSubcadeia[j]);
		sprintf(subcadeias, "%s\t%d", subcadeias, filtroSubcadeia[j]);
	}
	printf("\nSubcadeia: %s", subcadeias);
	
			
	return (subcadeias);
}
     

int main(int argc, char *argv[]) {
	// verificando quantidade de parametros passados.
	if (argc <= 1){
		printf("\nParâmetro Incorreto! --- %d\n", argc);
	}else{
		printf("%s", argv[1]);		
	 	FILE *entrada;	// Arquivos de Entrada e Saida.
	 	FILE *saida;
	 	size_t len = 0; // valor arbitrário para usar getLine
	 	
	 	char *linha = malloc(len);	// linha para leitura de sequencia.
	 	char *subcadeias = malloc(2*len);
	 	int contSubCadeias;
	 	
	 	int i, tamanhoEstrutura;
	 	
	 	char estrutura[TAM_MAX_SEQ];
	 	
	 	//Abrindo arquivo de entrada.
	 	if ((entrada = fopen(argv[1], "r")) == NULL){
	 		printf("ERRO ao abrir o arquivo de leitura!\n");
	 		return(0);
	 	}
	 		 	 	
	 	//Abrindo arquivo de escrita (saida).	 	
	 	if ((saida = fopen(argv[2], "w")) == NULL){
	 		printf("ERRO ao abrir o arquivo de escrita!\n");
	 		return(0);
	 	}
	 		 	
	 	tamanhoEstrutura = 0;
		while (getline(&linha, &len, entrada) > 0){
			// Verificando se a linha refere-se a descrção FASTA
			if (strlen(linha) >= 18 && linha[5] == 'S' && linha[6] == 'S'  && linha[7] == '_' && 
				linha[8] == 'c' && linha[9] == 'o'  && linha[10] == 'n' && 
				linha[11] == 's'){
				
				for (i=18; i<(strlen(linha)-1); i++){
					if ((linha[i] == '(')||(linha[i] == ')')||(linha[i] == '.')){										
						estrutura[tamanhoEstrutura] = linha[i];
				 		tamanhoEstrutura++;			
					}else if ((linha[i] == ',')||(linha[i] == '_')||
							  (linha[i] == ':')||(linha[i] == ',')||
							  (linha[i] == '-')||(linha[i] == '~')) {
						estrutura[tamanhoEstrutura] = '.';
				 		tamanhoEstrutura++;		
					}else if ((linha[i] == '<')||(linha[i] == '[')||(linha[i] == '{')) {
						estrutura[tamanhoEstrutura] = '(';
				 		tamanhoEstrutura++;		
					}else if ((linha[i] == '>')||(linha[i] == ']')||(linha[i] == '}')){
						estrutura[tamanhoEstrutura] = ')';
				 		tamanhoEstrutura++;		
					}
				} 
			}
		}
		estrutura[tamanhoEstrutura] = '\0';
			
		printf("\nEstrutura: %s", estrutura);
		
		// Extrair subcadeias da estrutura secundaria.
		subcadeias = extraiSubCadeias(estrutura, &contSubCadeias);
		printf("\nSubcadeias: %s", subcadeias);
		
		fprintf(saida, "%s\t%d\t%s\n", estrutura, contSubCadeias, subcadeias);	
     	
      	fclose(entrada);
      	fclose(saida);
	 	   
		printf("\nFIM!\n");
		//return(1);
	}	
}
